#include "ebnetwork.h"
//#include <QtConcurrent>
#include <QDebug>
#include <QProcess>

Q_GLOBAL_STATIC(EBNetwork,m_ebnetwork)
EBNetwork::EBNetwork(QObject *parent) : QObject(parent)
{
    init();
    //checkNet();
}

EBNetwork::~EBNetwork()
{
    if(m_thd){
        m_thd->quit();
        m_thd->wait();
    }
}

EBNetwork *EBNetwork::Get()
{
    return m_ebnetwork;
}

void EBNetwork::init()
{
    m_thd = new QThread();
    this->moveToThread(m_thd);
#ifdef RIGOROUS
    connect(m_thd,&QThread::started,this,&EBNetwork::checkNetworkLoop);
#else
    connect(m_thd,&QThread::started,this,&EBNetwork::existOneHaveNet);
#endif
    connect(m_thd,&QThread::finished,this,&QThread::deleteLater);
    connect(m_thd,&QThread::destroyed,this,&EBNetwork::deleteLater);
    
    m_thd->start();
}

bool EBNetwork::checkNet()
{
    while(!m_isStartPing){
        qDebug()<<__func__<<"not start!";
        QThread::msleep(500);
    }
    return netStatus();
}
//TODO 存在一个没通就判定没网
void EBNetwork::checkNetworkLoop()
{
    qDebug()<<"> "<<"function:"<<__FUNCTION__<<"thread id:"<<QThread::currentThreadId();
    do{
        bool re = false;
        QString ip;
        
        if(m_quitCheck){
            qDebug()<<"thread quick!";
            break;
        }
        //ping firm
        if(!PingTest(URL_FIRM_LOGIN)){
            re = false;
            qDebug()<<__func__<<URL_FIRM_LOGIN;
            goto Finished;
        }
        //qDebug("ping %s,status:%d",URL_FIRM_LOGIN,re);
        
        if(!PingTest(URL_FIRM_GRPC)){
            re = false;
            qDebug()<<__func__<<URL_FIRM_GRPC;
            goto Finished;
        }
        //qDebug("ping %s,status:%d",URL_FIRM_GRPC,re);
        
        if(!PingTest(URL_BAIDU)){
            re = false;
            qDebug()<<__func__<<URL_BAIDU;
            goto Finished;
        }
        //qDebug("ping %s,status:%d",URL_BAIDU,re);
        
        if(GetGateWay(ip)){
            if(!PingTest(ip))
            {
                re = false;
                goto Finished;
            }
        }
        else{
            qDebug() << "GetGateWay failed";
            re = false;
            goto Finished;
        }
        
        re = true;
    Finished:
        setNetStatus(re);
        if(m_isStartPing)
            QThread::msleep(5*1000);
        m_isStartPing = true;
        
    }while(1);
}

void EBNetwork::existOneHaveNet()
{
    qDebug()<<"> "<<"function:"<<__FUNCTION__<<"thread id:"<<QThread::currentThreadId();
    do{
        bool re = false;
        QString ip;
        if(m_quitCheck){
            qDebug()<<"thread quick!";
            break;
        }
        
        if(PingTest(URL_FIRM_LOGIN)){
            re = true;
            goto Finished;
        }
        
        if(PingTest(URL_FIRM_GRPC)){
            re = true;
            goto Finished;
        }
        
        if(PingTest(URL_BAIDU)){
            re = true;
            goto Finished;
        }
        
        if(GetGateWay(ip)){
            if(PingTest(ip))
            {
                re = true;
                goto Finished;
            }
        }
        else{
            qDebug() << "GetGateWay failed";
            re = false;
            goto Finished;
        }
    Finished:
        setNetStatus(re);
        if(m_isStartPing)
            QThread::msleep(5*1000);
        m_isStartPing = true;
    }while(true);
}

bool EBNetwork::PingTest(const QString &ip)
{
    QString cmd = QLatin1String("ping -c 1 ") + ip + QLatin1String(" -w 1");
    
    QProcess pro;
    pro.start(QLatin1String("bash"), QStringList() << QLatin1String("-c") << cmd);
    pro.waitForStarted();
    pro.waitForFinished();
    
    QTextStream txtStream(&pro);
    QString result = txtStream.readAll();
    
    int indexOfPin = result.indexOf(QLatin1String("ttl="));
    if(indexOfPin > 0)
    {
        return true;		// ping成功
    }
    
    return false;		// ping失败
}

bool EBNetwork::GetGateWay(QString &ip)
{
    QString cmd = QLatin1String("route -n | awk '{print $1,$2,$4}'");
    QProcess pro;
    pro.start(QLatin1String("bash"), QStringList() << QLatin1String("-c") << cmd);
    pro.waitForStarted();
    pro.waitForFinished();
    QTextStream txtStream(&pro);
    
    while(1)
    {
        QString result = txtStream.readLine();
        if(result.isEmpty())
            break;
        
        QStringList list = result.split(QLatin1String(" "));
        if(list.size() < 3)
            continue;
        
        for(int i=0; i<list.size(); i++)
        {
            if(list.at(0) == QLatin1String("0.0.0.0"))
            {
                if( list.at(2) == QLatin1String("UG") || list.at(2) == QLatin1String("UGH"))
                {
                    ip = list.at(1);
                    //qDebug() << "gateway:" << ip;
                    return true;
                }
            }
        }
    }
    
    return false;
}

bool EBNetwork::netStatus() const
{
    return m_netStatus;
}

void EBNetwork::setNetStatus(bool netStatus)
{
    if(m_netStatus != netStatus){
        m_netStatus = netStatus;
        Q_EMIT netStatusChanged();
        return;
    }
}


void EBNetwork::on_quit()
{
    m_quitCheck = true;
}
